// Copyright 2018 The Flutter team. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:flutter/material.dart';
import 'package:english_words/english_words.dart';

void main() => runApp(MyApp());

//Stateless widgets 是不可变的，这意味着它们的属性不能改变 —— 所有的值都是 final。
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        title: 'Flutter Learning',
        theme: ThemeData(
          primaryColor: Colors.black
        ),
        home: RandomWords()
    );
  }
}

//Stateless widgets 是不可变的，这意味着它们的属性不能改变 —— 所有的值都是 final。
//
// Stateful widgets 持有的状态可能在 widget 生命周期中发生变化，实现一个 stateful widget 至少需要两个类：
// 1）一个 StatefulWidget 类；
// 2）一个 State 类，StatefulWidget 类本身是不变的，但是 State 类在 widget 生命周期中始终存在。
// stful 快速创建 Flutter 模板代码
class RandomWords extends StatefulWidget {
  const RandomWords() : super();

  @override
  _RandomWordsState createState() => _RandomWordsState();
}

//默认情况下，State 类的名称带有下划线前缀。 Dart 语言中，给标识符加上下划线前缀可以 增强隐私性
// 并且这也是针对 State 对象推荐的最佳实践写法。
class _RandomWordsState extends State<RandomWords> {
  //保存建议的单词对
  final _suggestions = <WordPair>[];

  //增大字体大小
  final _biggerFont = const TextStyle(fontSize: 18.0);

  //存储喜欢的单词对
  final Set<WordPair> _saved = new Set<WordPair>();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter Learning'),
        actions: [
          IconButton(icon: const Icon(Icons.list), onPressed: _pushSaved)
        ],
      ),
      body: _buildSuggestions(),
    );
  }

  //ListView 类提供了一个名为 itemBuilder 的 builder 属性，这是一个工厂匿名回调函数，
  // 接受两个参数 BuildContext 和行迭代器 i。
  // 迭代器从 0 开始，每调用一次该函数 i 就会自增，
  // 每次建议的单词对都会让其递增两次，一次是 ListTile，另一次是 Divider。
  // 它用于创建一个在用户滚动时候无限增长的列表。
  Widget _buildSuggestions() {
    return ListView.builder(
      //注意 const: 父控件使用const修饰,是一个常量,所以子控件里不能有一个变量,解决方法,去掉const
      padding: const EdgeInsets.all(16.0),
      //对于每个建议的单词对都会调用一次 itemBuilder，然后将单词对添加到 ListTile 行中。
      // 在偶数行，该函数会为单词对添加一个 ListTile row，
      // 在奇数行，该函数会添加一个分割线的 widget，来分隔相邻的词对。
      // 注意，在小屏幕上，分割线看起来可能比较吃力。
      itemBuilder: (context, i) {
        //如果是奇数则返回一个分割线
        if (i.isOdd) return const Divider();
        //语法 i ~/ 2 表示 i 除以 2，但返回值是整型（向下取整），
        // 比如 i 为：1, 2, 3, 4, 5 时，结果为 0, 1, 1, 2, 2，
        // 这个可以计算出 ListView 中减去分隔线后的实际单词对数量。
        final index = i ~/ 2;
        //如果是建议列表中最后一个单词对，接着再生成10个单词对，然后添加到建议列表。
        if (index >= _suggestions.length) {
          _suggestions.addAll(generateWordPairs().take(10));
        }
        //print("_buildSuggestions | $i $index");
        return _buildRow(_suggestions[index]);
      },
    );
  }

  //对于每一个单词对，_buildSuggestions() 都会调用一次 _buildRow()。
  // 这个函数在 ListTile 中显示每个新词对，这使你在下一步中可以生成更漂亮的显示行
  Widget _buildRow(WordPair pair) {
    //是否已经选中
    final bool alreadySaved = _saved.contains(pair);

    return ListTile(
      title: Text(pair.asPascalCase, style: _biggerFont),
      trailing: Icon(
        alreadySaved ? Icons.favorite : Icons.favorite_border,
        color: alreadySaved ? Colors.red : null,
      ),
      onTap: () {
        // 触发点击
        setState(() {
          if (alreadySaved) {
            _saved.remove(pair);
          } else {
            _saved.add(pair);
          }
        });
      },
    );
  }

  // 在 Flutter 中，导航器管理应用程序的路由栈。将路由推入（push）到导航器的栈中，将会显示更新为该路由页面。
  // 从导航器的栈中弹出（pop）路由，将显示返回到前一个路由。
  //（当用户点击导航栏中的列表图标时）我们会建立一个路由并将其推入到导航管理器栈中。
  // 此操作会切换页面以显示新路由，新页面的内容会在 MaterialPageRoute 的 builder 属性中构建，builder 是一个匿名函数。
  void _pushSaved() {
    Navigator.of(context).push(
      new MaterialPageRoute<void>(
        builder: (BuildContext context) {
          //迭代取出数据
          final Iterable<ListTile> tiles = _saved.map(
            (WordPair pair) {
              return new ListTile(
                title: new Text(
                  pair.asPascalCase,
                  style: _biggerFont,
                ),
              );
            },
          );
          final List<Widget> divided = ListTile.divideTiles(
            context: context,
            tiles: tiles,
          ).toList();

          return GestureDetector(
            onTap: () {
              print('外层点击');
            },
            onTapDown: (t) {
              print("onTapDown: x: ${t.globalPosition.dx}");
              print("onTapDown: y: ${t.globalPosition.dy}");
            },
            child: new Scaffold(
              appBar: new AppBar(
                title: const Text('Saved Suggestions'),
              ),
              body:  GestureDetector(
                onTap: () {
                  print('内层点击');
                },
                child: new ListView(children: divided),
              ),
            ),
          );
        },
      ),
    );
  }
}

